package cn.cj.erp.service;

import cn.cj.erp.bo.system.SysMenuBo;
import cn.cj.erp.bo.system.SysNoticeBo;
import cn.cj.erp.bo.system.SysUserBo;
import cn.cj.erp.common.config.AppConfig;
import cn.cj.erp.common.constants.SystemConstants;
import cn.cj.erp.common.enums.MenuTypeEnum;
import cn.cj.erp.common.redis.RedisCache;
import cn.cj.erp.common.security.security.service.PermissionService;
import cn.cj.erp.common.vo.MetaVo;
import cn.cj.erp.common.vo.RouterVo;
import cn.cj.erp.common.vo.login.LoginUserResponseVo;
import cn.cj.erp.service.system.SysMenuService;
import cn.cj.erp.service.system.SysNoticeService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 登录相关业务逻辑
 *
 * @author jianchen
 */
@Slf4j
@Service
public class LoginService {
    @Resource
    private RedisCache redisCache;
    @Resource
    private SysMenuService sysMenuService;
    @Resource
    private SysNoticeService sysNoticeService;
    @Resource
    private PermissionService permissionService;

    /**
     * 获取登录用户信息
     * @return 用户信息
     */
    public LoginUserResponseVo getLoginUserInfo(SysUserBo sysUser) {
        sysUser.setPassword(null);
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(sysUser);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(sysUser);
        // 待读取公告
        List<SysNoticeBo> noticeList = sysNoticeService.listByUserId(sysUser.getUserId());
        // 组装响应体
        LoginUserResponseVo vo = new LoginUserResponseVo();
        vo.setVersion(AppConfig.getVersion());
        vo.setUser(sysUser);
        vo.setRoles(roles);
        vo.setPermissions(permissions);
        vo.setSysNoticeList(noticeList);
        return vo;
    }

    public List<RouterVo> getRouters(Long userId) {
        SysMenuBo params = new SysMenuBo();
        params.setMenuTypes(Arrays.asList(MenuTypeEnum.CATALOG, MenuTypeEnum.MENU));
        if (!SystemConstants.SUPER_ADMIN.equals(userId)) {
            params.setUserId(userId);
        }
        List<SysMenuBo> list = sysMenuService.queryTree(params);
        return recursionWrapRouter(list);
    }

    /**
     * 递归将实体类树转化为路由树
     * @param menus 菜单列表
     * @return 路由列表
     **/
    private List<RouterVo> recursionWrapRouter(List<SysMenuBo> menus) {
        List<RouterVo> routers = new LinkedList<>();
        for (SysMenuBo menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden(menu.getVisible().isNo());
            router.setName(getRouteName(menu));
            router.setPath(getRouterPath(menu));
            router.setComponent(getComponent(menu));
            router.setQuery(menu.getQuery());
            router.setFrame(menu.getFrame().getValue().toString());
            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getCache().isNo(), null));
            List<SysMenuBo> cMenus = menu.getChildren();
            if (CollectionUtil.isNotEmpty(cMenus) && MenuTypeEnum.CATALOG.equals(menu.getMenuType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(recursionWrapRouter(cMenus));
            } else if (isMenuFrame(menu)) {
                List<RouterVo> childrenList = new ArrayList<>();
                RouterVo children = new RouterVo();
                children.setPath(menu.getPath());
                children.setComponent(menu.getComponent());
                children.setName(StrUtil.upperFirst(menu.getPath()));
                children.setFrame(menu.getFrame().getValue().toString());
                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getCache().isNo(), null));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由名称
     *
     * @param menu 菜单信息
     * @return 路由名称
     */
    private String getRouteName(SysMenuBo menu) {
        String routerName = StrUtil.upperFirst(menu.getPath());
        if (isMenuFrame(menu)) {
            routerName = StrUtil.EMPTY;
        }
        return routerName;
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    private String getRouterPath(SysMenuBo menu) {
        String routerPath = menu.getPath();
        if (isCatalog(menu)) {
            routerPath = "/" + menu.getPath();
        } else if (isMenuFrame(menu)) {
            routerPath = "/";
        }
        return routerPath;
    }

    /**
     * 获取组件信息
     *
     * @param menu 菜单信息
     * @return 组件信息
     */
    private String getComponent(SysMenuBo menu) {
        String component = SystemConstants.LAYOUT;
        if (StrUtil.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
            component = menu.getComponent();
        } else if (StrUtil.isEmpty(menu.getComponent()) && isParentView(menu)) {
            component = SystemConstants.PARENT_VIEW;
        }
        return component;
    }

    /**
     * 是否为目录（非外链）
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isCatalog(SysMenuBo menu) {
        return SystemConstants.TREE_ROOT.equals(menu.getParentId())
                && MenuTypeEnum.CATALOG.equals(menu.getMenuType())
                && menu.getFrame().isNo();
    }

    /**
     * 是否为菜单内部跳转
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isMenuFrame(SysMenuBo menu) {
        return SystemConstants.TREE_ROOT.equals(menu.getParentId())
                && MenuTypeEnum.MENU.equals(menu.getMenuType())
                && menu.getFrame().isNo();
    }

    /**
     * 是否为parent_view组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    private boolean isParentView(SysMenuBo menu) {
        return !SystemConstants.TREE_ROOT.equals(menu.getParentId())
                && MenuTypeEnum.CATALOG.equals(menu.getMenuType());
    }
}